#include "StdAfx.h"
#include "ServerEnumerator.h"

using namespace Adaptive::Foundation;
using namespace Adaptive::Win32;
using namespace Adaptive::Win32::Network;

/*--------------------------------------------------------------------------------
 * Constructor / Dispose / Destructor Methods
 *------------------------------------------------------------------------------*/
#pragma region Constructor / Dispose / Destructor Methods
// <summary>
// Initializes a new instance of the class.
// </summary>
// <remarks>
// This constructor is hidden to prevent instantiation.
// </remarks>
ServerEnumerator::ServerEnumerator()
{
}
#pragma endregion

/*--------------------------------------------------------------------------------
 * Public Methods / Functions
 *------------------------------------------------------------------------------*/
#pragma region Public Methods / Functions
// <summary>
// Lists the workstations on the local network.
// </summary>
// <returns>
// A <see cref="ServerInformation"/> array containing the list of machines on the network.
// </returns>
array<ServerInformation>^ ServerEnumerator::EnumerateWorkstations(String^ domain)
{
	return UnmanagedEnumerate((int)ServerType::Workstation, domain);
}
// <summary>
// Lists the servers on the local network.
// </summary>
// <returns>
// A <see cref="ServerInformation"/> array containing the list of machines on the network.
// </returns>
array<ServerInformation>^ ServerEnumerator::EnumerateServers(String^ domain)
{
	return UnmanagedEnumerate((int)ServerType::Server, domain);
}
// <summary>
// Lists the SQL Servers on the local network.
// </summary>
// <returns>
// A <see cref="ServerInformation"/> array containing the list of machines on the network.
// </returns>
array<ServerInformation>^ ServerEnumerator::EnumerateSqlServers(String^ domain)
{
	return UnmanagedEnumerate((int)ServerType::SqlServer, domain);
}
// <summary>
// Lists the primary domain controllers on the local network.
// </summary>
// <returns>
// A <see cref="ServerInformation"/> array containing the list of machines on the network.
// </returns>
array<ServerInformation>^ ServerEnumerator::EnumeratePrimaryDcs(String^ domain)
{
	return UnmanagedEnumerate((int)ServerType::DomainController, domain);
}
// <summary>
// Lists the backup domain controllers on the local network.
// </summary>
// <returns>
// A <see cref="ServerInformation"/> array containing the list of machines on the network.
// </returns>
array<ServerInformation>^ ServerEnumerator::EnumerateBackupDcs(String^ domain)
{
	return UnmanagedEnumerate((int)ServerType::BackupDomainController, domain);
}
// <summary>
// Lists the NT Servers on the local network.
// </summary>
// <returns>
// A <see cref="ServerInformation"/> array containing the list of machines on the network.
// </returns>
array<ServerInformation>^ ServerEnumerator::EnumerateNtServers(String^ domain)
{
	return UnmanagedEnumerate((int)ServerType::WindowsNTServer, domain);
}
// <summary>
// Lists the all the machines on the local network.
// </summary>
// <returns>
// A <see cref="ServerInformation"/> array containing the list of machines on the network.
// </returns>
array<ServerInformation>^ ServerEnumerator::EnumerateAll(String^ domain)
{
	return UnmanagedEnumerate((int)ServerType::All, domain);
}
// <summary>
// Lists the machines on the local network of the specified server type.
// </summary>
// <param name="typeOfServer">A <see cref="ServerType"/> enumerated value indicating the 
// type(s) of servers and/or workstations to be enumerated.</param>
// <returns>
// A <see cref="ServerInformation"/> array containing the list of machines on the network.
// </returns>
array<ServerInformation>^ ServerEnumerator::EnumerateByType( ServerType typeOfServer, String^ domain )
{
	return UnmanagedEnumerate((int)typeOfServer, domain);
}
#pragma endregion

/*--------------------------------------------------------------------------------
 * Private Methods / Function
 *------------------------------------------------------------------------------*/
#pragma region Private Methods / Functions

array<ServerInformation>^ ServerEnumerator::UnmanagedEnumerate(int serverType, String^ domainName)
{
	NET_API_STATUS		result = 0;
	SERVER_INFO_101*	buffer = NULL;
	DWORD				entriesRead;
	DWORD				totalEntries;
	array<ServerInformation>^ returnValue = nullptr;
	DWORD				count = 0;
	CString				dmName = domainName;

	result = NetServerEnum(NULL, 101, (LPBYTE*)&buffer, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, (DWORD)serverType, dmName, 0);

	if (result == NERR_Success)
	{
		returnValue = gcnew array<ServerInformation>(entriesRead);
		for(count = 0; count < entriesRead; count++)
		{
			returnValue[count].PlatformId = (ServerPlatformType)buffer[count].sv101_platform_id;
			returnValue[count].ServerName = gcnew String( buffer[count].sv101_name );
			returnValue[count].MajorVersion = buffer[count].sv101_version_major;
			returnValue[count].MinorVersion = buffer[count].sv101_version_minor;
			returnValue[count].ServerType = (ServerType)buffer[count].sv101_type;
			returnValue[count].Comment = gcnew String( buffer[count].sv101_comment );
		}

		NetApiBufferFree(buffer);
	}

	return returnValue;
}
#pragma endregion
